#!/usr/bin/env python
# # -*- coding: utf-8 -*-

from string import Template
import urllib
import json
from constant import Constant as c
from singleton import Singleton
from strategy import MoreInfoMode, DefaultMode
import signal
import sys
from terminalColor import TerminalColor


class API(object):
    ''' Refined abstraction class '''

    # using metaclass to produce a singleton class
    __metaclass__ = Singleton

    def __init__(self, apiObj):
        self.apiObj = apiObj
        self.requestWord = ''
        self.showModes = {'default': DefaultMode(), 
            'detail': MoreInfoMode(),
        }

    def paintMeBlue(self, words):
        return TerminalColor.OKBLUE + words + TerminalColor.ENDC

    def setShowStrategy(self):
        # check if the word beginnig with '+'
        # NOTE: maybe we need a setter here, if user wants 
        # more details, we change the default behavior to detail
        if len(self.requestWord) > 1 and \
            self.requestWord.startswith(c.MODE_DETAIL_LEADING_CHAR):
            self.showMode = self.showModes['detail']

            # strip the leading +
            self.requestWord = self.requestWord[1:]
        else:
            self.showMode = self.showModes['default']

    def getInput(self):
        remind_words = self.paintMeBlue('Please Input your word: ');
        self.requestWord = raw_input(remind_words)
        
        # get rid of leading and trailing whitespace
        self.requestWord = self.requestWord.strip()

        # if user input $$, we can quit now
        if self.requestWord == '$$':
            print c.BYE
            sys.exit(0)
        
        # user hits 'Return' with no chars input, maybe he is too
        # stinginess, :/
        if not self.requestWord:
            self.requestWord = c.KIDDING_EMPTY

        # get show strategy, determined by the leading character
        # of course, this function needs self.requestWord
        # if users inputs '+help', that's detail mode
        # setShowStrategy will strip off the leading '+'
        self.setShowStrategy()

    def getTranslated(self):
        self.apiObj.postRequest(self.requestWord)
        results = self.apiObj.getResult()
        
        self.showMode.show(results)


class YoudaoDictAPI(object):
    ''' implemetator: define more primitive operations '''
    def __init__(self):
        self.URL = Template('http://fanyi.youdao.com/openapi.do?'
            'keyfrom=${KeyFrom}&key=${Key}&type=data&doctype=${DocType}&version=1.1&q='
        )

        self.KeyFrom = c.KEYFROM
        self.Key = c.KEY
        self.DocType = c.DOCTYPE

        self.setUrl()

    def setAPIKey(self, key):
        self.Key = key

    def setKeyFrom(self, keyFrom):
        self.KeyFrom = keyFrom

    def setUrl(self):
        self.URL = self.URL.substitute(KeyFrom=self.KeyFrom, Key=self.Key, 
            DocType=self.DocType,
        )

    def getRequestURL(self):
        return self.URL

    def postRequest(self, request):
        ''' Handle json formatted result, return dict '''
        url = self.getRequestURL()
        f = urllib.urlopen(url + urllib.quote(request))
        self.result = f.read()

    def formatResult(self):
        self.resultDict = json.loads(self.result)

    def getResult(self):
        self.formatResult() 
        return self.resultDict

# signal handler for Ctrl + C
# Reference: 
# http://docs.python.org/library/signal.html
def signal_handler(signal, frame):
    print c.BYE
    sys.exit(0)

if __name__ == '__main__':
    signal.signal(signal.SIGINT, signal_handler)

    youdaoAPI = YoudaoDictAPI()
    yd = API(youdaoAPI)

    print 'Pay me two $, i will quit :)'

    while True:
        yd.getInput()
        yd.getTranslated()
